package com.example.spring.test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Lock锁分为：公平锁 和 非公平锁。公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的，即先来先得的FIFO先进先出顺序。
 * 而非公平锁就是一种获取锁的抢占机制，是随机获取锁的，和公平锁不一样的就是先来的不一定先的到锁，这样可能造成某些线程一直拿不到锁，结果也就是不公平的了。
 */
public class ConditionSeqExec {

    volatile private static int nextPrintWho = 1;

    // 默认情况下ReentranLock类使用的是非公平锁
    final private static ReentrantLock lock = new ReentrantLock();

    final private static Condition conditionA = lock.newCondition();
    final private static Condition conditionB = lock.newCondition();
    final private static Condition conditionC = lock.newCondition();

    public static void main(String[] args) {


        Thread threadA = new Thread() {
            public void run() {
                lock.lock();
                try {
                    while (nextPrintWho != 1) {
                        conditionA.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadA" + (i + 1));
                    }

                    nextPrintWho = 2;
                    //通知conditionB实例的线程运行

                    conditionB.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };

        Thread threadB = new Thread() {
            public void run() {
                lock.lock();
                try {
                    while (nextPrintWho != 2) {
                        conditionB.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadB" + (i + 1));
                    }

                    nextPrintWho = 3;
                    //通知conditionB实例的线程运行

                    conditionC.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };

        Thread threadC = new Thread() {
            public void run() {
                lock.lock();
                try {
                    while (nextPrintWho != 3) {
                        conditionC.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("ThreadC" + (i + 1));
                    }

                    nextPrintWho = 1;
                    //通知conditionB实例的线程运行

                    conditionA.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };

        Thread[] array1 = new Thread[5];
        Thread[] array2 = new Thread[5];
        Thread[] array3 = new Thread[5];

        for (int i = 0; i < 5; i++) {
            array1[i] = new Thread(threadA);
            array2[i] = new Thread(threadB);
            array3[i] = new Thread(threadC);

            array1[i].start();
            array2[i].start();
            array3[i].start();
        }
    }

}
